package timing.ukulele.minio.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import timing.ukulele.common.data.ResponseData;
import timing.ukulele.minio.model.FileCheckModel;
import timing.ukulele.minio.model.FileCompleteModel;
import timing.ukulele.minio.model.PreShardingModel;
import timing.ukulele.minio.service.StorageService;
import timing.ukulele.minio.vo.CompleteResultVO;
import timing.ukulele.minio.vo.FileCheckResultVO;
import timing.ukulele.minio.vo.FilePreShardingVO;

/**
 * 对象存储标准接口定义
 * 本类的方法是给前端使用的方法
 */
@Slf4j
@RestController
@RequestMapping("/storage")
@Tag(name = "存储接口")
public class OssController {

    /**
     * 存储引擎Service接口定义
     */
    private final StorageService storageService;

    /**
     * 构造方法
     *
     * @param storageService 注入存储引擎Service接口定义实现类
     */
    public OssController(StorageService storageService) {
        this.storageService = storageService;
    }

    /**
     * 文件预分片方法
     * 在大文件上传时，为了防止前端重复计算文件MD5值，提供该方法
     *
     * @param preShardingDTO 文件预分片入参DTO
     * @return 预分片结果
     */
    @Operation(summary = "文件预分片")
    @PostMapping("/upload/sharding")
    public ResponseData<FilePreShardingVO> sharding(@RequestBody @Validated PreShardingModel preShardingDTO) {
        FilePreShardingVO resultVo = storageService.sharding(preShardingDTO.getFileSize());
        return ResponseData.success(resultVo);
    }

    /**
     * 上传任务初始化
     * 上传前的预检查：秒传、分块上传和断点续传等特性均基于该方法实现
     *
     * @param fileCheckDTO 文件预检查入参
     * @return 检查结果
     */
    @Operation(summary = "上传任务初始化")
    @PostMapping("/upload/init")
    ResponseData<FileCheckResultVO> init(@RequestHeader("X-USER") String userId, @RequestBody @Validated FileCheckModel fileCheckDTO) {
        FileCheckResultVO resultVo = storageService.init(fileCheckDTO.getFileMd5(), fileCheckDTO.getFullFileName(), fileCheckDTO.getFileSize(), fileCheckDTO.getIsPrivate(), userId);
        return ResponseData.success(resultVo);
    }

    /**
     * 文件上传完成
     *
     * @param fileKey         文件KEY
     * @param fileCompleteDTO 文件完成入参DTO
     * @return 是否成功
     */
    @Operation(summary = "上传完成")
    @PostMapping("/upload/complete/{fileKey}")
    ResponseData<Object> complete(@RequestHeader("X-USER") String userId, @PathVariable("fileKey") String fileKey, @RequestBody FileCompleteModel fileCompleteDTO) {
        // 打印调试日志
        log.debug("合并文件开始fileKey={},partMd5List={}", fileKey, fileCompleteDTO.getPartMd5List());
        CompleteResultVO completeResultVo = storageService.complete(fileKey, fileCompleteDTO.getPartMd5List(), userId);
        return ResponseData.success(completeResultVo);
    }

    @Operation(summary = "删除文件", description = "只允许删除未上传完成的文件，并别会将未完成的分片进行清除")
    @DeleteMapping("/deleteNotComplete/{fileKey}")
    ResponseData<Boolean> deleteNotComplete(@RequestHeader("X-USER") String userId, @PathVariable("fileKey") String fileKey) {
        storageService.deleteNotComplete(fileKey);
        return ResponseData.success(Boolean.TRUE);
    }

    /**
     * 文件下载
     *
     * @param fileKey 文件KEY
     * @return 文件下载地址
     */
    @Operation(summary = "文件下载")
    @GetMapping("/download/{fileKey}")
    ResponseData<String> download(@RequestHeader("X-USER") String userId, @PathVariable("fileKey") String fileKey) {
        // 取得文件读取路径
        String downloadUrl = storageService.download(fileKey, userId);
        return ResponseData.success(downloadUrl);
    }

    /**
     * 获取图像
     *
     * @param fileKey 文件KEY
     * @return 原图地址
     */
    @Operation(summary = "图片预览 - 原图")
    @GetMapping("/image/{fileKey}")
    String previewOriginal(@RequestHeader("X-USER") String userId, @PathVariable("fileKey") String fileKey) {
        // 取得文件读取路径
        return storageService.image(fileKey, userId);
    }

    /**
     * 文件预览
     * 当文件为图片时，返回图片的缩略图
     * 当文件不是图片时，返回文件类型图标
     *
     * @param fileKey 文件KEY
     * @return 缩略图地址
     */
    @Operation(summary = "图片预览 - 缩略图")
    @GetMapping("/preview/{fileKey}")
    String previewMedium(@RequestHeader("X-USER") String userId, @PathVariable("fileKey") String fileKey) {

        String url = storageService.preview(fileKey, userId);
//        if (url.length() < 10) {
//            // 当返回值为文件类型时，取得图标
//            url = "/storage/icon/" + url;
//        }

        // 取得文件读取路径
        return url;
    }

//    /**
//     * 根据文件类型取得图标
//     *
//     * @param fileType 文件扩展名
//     */
//    @Operation(summary = "获取图标")
//    @GetMapping("/icon/{fileType}")
//    void icon(@PathVariable("fileType") String fileType) {
//        try {
//            // 根据文件后缀取得桶
//            String storageBucket = BucketEnums.getBucketByFileSuffix(fileType);
//
//            ClassPathResource cpr = new ClassPathResource(storageBucket + ".png");
//
//            byte[] bytes = FileCopyUtils.copyToByteArray(cpr.getInputStream());
//
//            ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//            attr.getResponse().setHeader("content-disposition", "inline");
//            attr.getResponse().setHeader("Content-Length", String.valueOf(bytes.length));
//            try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
//                IoUtil.copy(inputStream, attr.getResponse().getOutputStream());
//            }
//        } catch (Exception e) {
//            log.error(ErrorCode.FILE_ICON_FAILED.getMessage(), e);
//            // 图标获取失败
//            throw new OssException(ErrorCode.FILE_ICON_FAILED);
//        }
//    }

}